﻿using B.S.BasicData.API.Read.Application.Command.Leave;
using B.S.BasicData.API.Read.DTOS.Leave;
using B.S.BasicData.API.Read.DTOS.UserRoleMenu;
using B.S.BasicData.Domain.Entities.Leave;
using B.S.BasicData.ErrorCode;
using B.S.BasicData.Infrastructure.Interface;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Globalization;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;

namespace B.S.BasicData.API.Read.Application.Handler.Leave
{
    /// <summary>
    /// 查看个人在某个月的请假信息请求命令处理类
    /// </summary>
    public class GetLeavePresonDataHandler:IRequestHandler<GetLeavePresonDataCommand,ApiResult<List<LeaveDTO>>>
    {
        IBaseRepository<LeaveApplicationModel> leaveRep;
        IBaseRepository<LeaveTypeModel> leaveTypeRep;

        // 定义工作时间范围（9:00-17:00）
        private static readonly TimeSpan WorkStart = new TimeSpan(9, 0, 0);
        private static readonly TimeSpan WorkEnd = new TimeSpan(17, 0, 0);

        public GetLeavePresonDataHandler(IBaseRepository<LeaveApplicationModel> leaveRep, IBaseRepository<LeaveTypeModel> leaveTypeRep)
        {
            this.leaveRep = leaveRep;
            this.leaveTypeRep = leaveTypeRep;
        }

        public Task<ApiResult<List<LeaveDTO>>> Handle(GetLeavePresonDataCommand request, CancellationToken cancellationToken)
        {
            ApiResult<List<LeaveDTO>> res = new ApiResult<List<LeaveDTO>>();

            // 解析月份输入，返回当月起始和结束时间
            var (startOfMonth, endOfMonth) = ParseMonthInputToDateRange(request.startMonth);

            // 查询数据库（仅过滤日期，不处理时间）
            var rawLeaveData = leaveRep.GetAll()
                .Where(x => x.ApplicationName == request.leaveName && !x.IsDeleted&&x.State==LeaveStateEnum.已通过)
                .Where(lr => lr.StartTime <= endOfMonth && lr.EndTime >= startOfMonth) // 过滤出与当月有交集的请假记录
                .AsNoTracking()
                .ToList();

            var leavetypes = leaveTypeRep.GetAll();

            // 在内存中处理时间调整（仅调整跨月部分）
            var filteredResults = (from a in rawLeaveData
                                  join b in leavetypes on a.LeaveTypeId equals b.Id
                                  select new LeaveDTO
                                  {
                                      Id = a.Id,
                                      DepartmentId=a.DepartmentId,
                                      // 调整开始时间（如果早于当月第一天，则取当月第一天 9:00）
                                      StartTime = AdjustStartTime(a.StartTime, startOfMonth),
                                      // 调整结束时间（如果晚于当月最后一天，则取当月最后一天 17:00）
                                      EndTime = AdjustEndTime(a.EndTime, endOfMonth),
                                      Reason = a.Reason,
                                      LeaveTypeName=b.LeaveTypeName,
                                      ApplicationName=a.ApplicationName
                                  }).ToList();
                

            res.Msg = "获取某个人在某个月请假的数据";
            res.Code = ApiEnum.Success;
            res.Data = filteredResults.ToList();
            return Task.FromResult(res);

        }

        

        private DateTime AdjustStartTime(DateTime startTime, DateTime startOfMonth)
        {    
            // 如果请假开始时间早于当月第一天，则取当月第一天 9:00
            if (startTime < startOfMonth)
            {
                return AdjustToWorkTime(startOfMonth); // 调整到 9:00（如果是周末则返回当天 00:00）
            }

            // 否则，调整原始时间到工作时间（9:00-17:00）
            return AdjustToWorkTime(startTime);
        }

        private DateTime AdjustEndTime(DateTime endTime, DateTime endOfMonth)
        {
            // 如果请假结束时间晚于当月最后一天，则取当月最后一天 17:00
            if (endTime > endOfMonth)
            {
                return AdjustToWorkTime(endOfMonth); // 调整到 17:00（如果是周末则返回当天 00:00）
            }

            // 否则，调整原始时间到工作时间（9:00-17:00）
            return AdjustToWorkTime(endTime);
        }


        private DateTime AdjustToWorkTime(DateTime dateTime)
        {
            // 如果是周末，直接返回当天 00:00（可根据需求调整）
            if (dateTime.DayOfWeek == DayOfWeek.Saturday || dateTime.DayOfWeek == DayOfWeek.Sunday)
            {
                return dateTime.Date;
            }

            // 调整时间到 9:00-17:00
            TimeSpan timeOfDay = dateTime.TimeOfDay;
            if (timeOfDay < WorkStart)
            {
                return dateTime.Date.Add(WorkStart); // 最早 9:00
            }
            else if (timeOfDay > WorkEnd)
            {
                return dateTime.Date.Add(WorkEnd); // 最晚 17:00
            }

            return dateTime; // 在工作时间范围内，直接返回
        }

        private (DateTime startOfMonth, DateTime endOfMonth) ParseMonthInputToDateRange(string monthInput)
        {
            if (string.IsNullOrWhiteSpace(monthInput))
                throw new ArgumentException("月份参数不能为空");

            // 尝试解析 "yyyy-MM" 格式（如 "2023-07"）
            if (DateTime.TryParseExact(monthInput, "yyyy-MM", CultureInfo.InvariantCulture,
                                     DateTimeStyles.None, out var exactDate))
            {
                var startOfMonth = new DateTime(exactDate.Year, exactDate.Month, 1);
                return (startOfMonth, startOfMonth.AddMonths(1).AddDays(-1));
            }

            // 尝试解析 "MM" 格式（如 "07"），使用当前年份
            if (DateTime.TryParseExact(monthInput, "MM", CultureInfo.InvariantCulture,
                                     DateTimeStyles.None, out var monthDate))
            {
                var startOfMonth = new DateTime(DateTime.Now.Year, monthDate.Month, 1);
                return (startOfMonth, startOfMonth.AddMonths(1).AddDays(-1));
            }

            // 尝试解析中文或英文月份名称（如 "七月" 或 "June"）
            var monthNameFormats = new[] { "MMMM", "MMM" }; // "MMMM"=全称（七月），"MMM"=缩写（Jul）
            if (DateTime.TryParseExact(monthInput, monthNameFormats, CultureInfo.CurrentCulture,
                                     DateTimeStyles.None, out var monthNameDate))
            {
                var startOfMonth = new DateTime(DateTime.Now.Year, monthNameDate.Month, 1);
                return (startOfMonth, startOfMonth.AddMonths(1).AddDays(-1));
            }

            // 尝试解析 "M" 格式（如 "7"），补零后处理
            if (int.TryParse(monthInput, out var monthNum))
            {
                if (monthNum >= 1 && monthNum <= 12)
                {
                    var startOfMonth = new DateTime(DateTime.Now.Year, monthNum, 1);
                    return (startOfMonth, startOfMonth.AddMonths(1).AddDays(-1));
                }
            }

            throw new ArgumentException("月份格式无效。支持格式：'yyyy-MM'（如'2023-07'）、'MM'（如'07'）、'MMMM'（如'七月'）或'M'（如'7'）");
        }
    }
}
